---
import { getCollection, render } from "astro:content";
import type { CollectionEntry } from "astro:content";
import { getSpecialPath } from "@/content.config";
import Layout from "@/components/Layout.astro";
import Breadcrumb from "@/components/Breadcrumb.astro";
import { ARTICLE_EXPIRY_CONFIG } from "@/consts";
import "@/styles/articles.css";

// 定义文章类型
type ArticleEntry = CollectionEntry<"articles">;

// 定义标题类型
interface Heading {
  depth: number;
  slug: string;
  text: string;
}

// 生成文章摘要的辅助函数
function generateArticleSummary(article: ArticleEntry): string {
  if (article.data.summary) {
    return article.data.summary;
  }

  // 如果没有summary，从文章内容中提取
  const rawContent = article.body;
  // 移除Markdown语法和空白字符
  const plainText = rawContent
    .replace(/\s+/g, " ") // 将多个空白字符替换为单个空格
    .replace(/[#*`~>]/g, "") // 移除Markdown标记
    .replace(/\[.*?\]\(.*?\)/g, "") // 移除Markdown链接
    .replace(/!\[.*?\]\(.*?\)/g, "") // 移除Markdown图片
    .replace(/```[\s\S]*?```/g, "") // 移除代码块
    .trim();

  return plainText.length > 150
    ? plainText.substring(0, 150) + "..."
    : plainText;
}

export async function getStaticPaths() {
  const articles = await getCollection("articles");

  // 为每篇文章生成路由参数
  const paths = [];
  for (const article of articles) {
    // 获取所有可能的路径形式
    const possiblePaths = new Set([
      article.id, // 只保留原始路径
    ]);

    // 如果是多级目录，检查是否需要特殊处理
    if (article.id.includes("/")) {
      const parts = article.id.split("/");
      const fileName = parts[parts.length - 1];
      const dirName = parts[parts.length - 2];

      // 只有当文件名与其父目录名相同时才添加特殊路径
      if (fileName === dirName) {
        possiblePaths.add(getSpecialPath(article.id));
      }
    }

    // 为每个可能的路径生成路由
    for (const path of possiblePaths) {
      paths.push({
        params: { id: path },
        props: {
          article,
          section: article.id.includes("/")
            ? article.id.split("/").slice(0, -1).join("/")
            : "",
          originalId: path !== article.id ? article.id : undefined,
        },
      });
    }
  }

  return paths;
}

// 获取文章内容
const { article, section, originalId } = Astro.props;

// 获取搜索参数
const searchParams = new URLSearchParams(Astro.url.search);

// 如果有原始ID，使用它来渲染内容
const articleToRender = originalId ? { ...article, id: originalId } : article;

// 渲染文章内容
const { Content, headings } = await render(articleToRender);

// 获取面包屑路径段
const pathSegments = section ? section.split("/") : [];

// 获取相关文章
const allArticles = await getCollection("articles");

// 1. 尝试通过标签匹配相关文章
let relatedArticles = allArticles
  .filter((a: ArticleEntry) => {
    const hasCommonTags =
      a.id !== article.id &&
      a.data.tags &&
      article.data.tags &&
      a.data.tags.length > 0 &&
      article.data.tags.length > 0 &&
      a.data.tags.some((tag: string) => article.data.tags?.includes(tag));

    return hasCommonTags;
  })
  .sort(
    (a: ArticleEntry, b: ArticleEntry) =>
      b.data.date.getTime() - a.data.date.getTime(),
  )
  .slice(0, 3);

// 跟踪相关文章的匹配方式: "tag", "directory", "latest"
let relatedArticlesMatchType = relatedArticles.length > 0 ? "tag" : "";

// 2. 如果标签匹配没有找到足够的相关文章，尝试根据目录结构匹配
if (relatedArticles.length < 3) {
  // 获取当前文章的目录路径
  const currentPath = article.id.includes("/")
    ? article.id.substring(0, article.id.lastIndexOf("/"))
    : "";

  // 如果有目录路径，查找同目录的其他文章
  if (currentPath) {
    // 收集同目录下的文章，但排除已经通过标签匹配的和当前文章
    const dirRelatedArticles = allArticles
      .filter(
        (a: ArticleEntry) =>
          a.id !== article.id &&
          a.id.startsWith(currentPath + "/") &&
          !relatedArticles.some((r: ArticleEntry) => r.id === a.id),
      )
      .sort(
        (a: ArticleEntry, b: ArticleEntry) =>
          b.data.date.getTime() - a.data.date.getTime(),
      )
      .slice(0, 3 - relatedArticles.length);

    if (dirRelatedArticles.length > 0) {
      relatedArticles = [...relatedArticles, ...dirRelatedArticles];
      relatedArticlesMatchType =
        relatedArticles.length > 0 && !relatedArticlesMatchType
          ? "directory"
          : relatedArticlesMatchType;
    }
  }
}

// 3. 如果仍然没有找到足够的相关文章，则选择最新的文章（排除当前文章和已选择的文章）
if (relatedArticles.length < 3) {
  const latestArticles = allArticles
    .filter(
      (a: ArticleEntry) =>
        a.id !== article.id &&
        !relatedArticles.some((r: ArticleEntry) => r.id === a.id),
    )
    .sort(
      (a: ArticleEntry, b: ArticleEntry) =>
        b.data.date.getTime() - a.data.date.getTime(),
    )
    .slice(0, 3 - relatedArticles.length);

  if (latestArticles.length > 0) {
    relatedArticles = [...relatedArticles, ...latestArticles];
    relatedArticlesMatchType =
      relatedArticles.length > 0 && !relatedArticlesMatchType
        ? "latest"
        : relatedArticlesMatchType;
  }
}

// 准备文章描述
const description = generateArticleSummary(article);

// 处理特殊ID的函数 - 确保返回的是未编码的路径
function getArticleUrl(articleId: string) {
  // 获取特殊路径
  const path = getSpecialPath(articleId);
  // 添加搜索参数（如果有）
  const searchSuffix = searchParams.toString()
    ? `?${searchParams.toString()}`
    : "";
  return `/articles/${path}${searchSuffix}`;
}

// 预先生成目录结构
function generateTableOfContents(headings: Heading[]) {
  if (!headings || headings.length === 0) {
    return '<p class="text-gray-500 dark:text-gray-400 italic">此文章没有目录</p>';
  }

  // 查找最低级别的标题（数值最小）
  const minDepth = Math.min(...headings.map((h) => h.depth));

  // 按照标题层级构建嵌套结构
  const tocTree: any[] = [];
  const levelMap: Record<number, any[]> = {};

  headings.forEach((heading) => {
    const relativeDepth = heading.depth - minDepth;

    // 构建标题项
    const headingItem = {
      slug: heading.slug,
      text: heading.text,
      depth: relativeDepth,
      children: [],
    };

    // 更精确地处理嵌套关系
    if (relativeDepth === 0) {
      // 顶级标题直接加入到树中
      tocTree.push(headingItem);
      levelMap[0] = tocTree;
    } else {
      // 查找当前标题的父级
      let parentDepth = relativeDepth - 1;
      // 向上查找可能的父级
      while (parentDepth >= 0 && !levelMap[parentDepth]) {
        parentDepth--;
      }

      if (
        parentDepth >= 0 &&
        levelMap[parentDepth] &&
        levelMap[parentDepth].length > 0
      ) {
        // 找到父层级，将此标题添加到最近的父标题的子标题数组中
        const parentItems = levelMap[parentDepth];
        const parent = parentItems[parentItems.length - 1];
        parent.children.push(headingItem);

        // 更新当前深度的映射
        if (!levelMap[relativeDepth]) {
          levelMap[relativeDepth] = [];
        }
        levelMap[relativeDepth].push(headingItem);
      } else {
        // 找不到有效父级，作为顶级标题处理
        tocTree.push(headingItem);
        levelMap[relativeDepth] = [headingItem];
      }
    }
  });

  // 递归生成HTML
  function generateTocHTML(items: any[], level = 0) {
    if (items.length === 0) return "";

    const isTopLevel = level === 0;
    let html = `<ul class="toc-list space-y-2 ${isTopLevel ? "" : "toc-sublist hidden"}" ${level > 0 ? 'aria-expanded="false"' : ""}>`;

    items.forEach((item) => {
      const hasChildren = item.children && item.children.length > 0;
      const isHigherLevel = item.depth <= 1; // 只有最高级和次高级标题使用较重的样式

      html += `<li class="toc-item" data-depth="${item.depth}">
        <div class="toc-item-container">
          <a href="#${item.slug}" 
             class="toc-link ${
               isHigherLevel
                 ? "text-gray-800 dark:text-gray-200 font-medium"
                 : "text-gray-600 dark:text-gray-400"
             } hover:text-primary-600 dark:hover:text-primary-400"
             style="padding-left: ${item.depth * 0.75}rem;">
            ${item.text}
          </a>
          ${
            hasChildren
              ? `<button class="toc-toggle text-gray-400 hover:text-primary-600 dark:hover:text-primary-400 ml-1 p-1" aria-expanded="false">
            <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
          </button>`
              : ""
          }
        </div>
        ${generateTocHTML(item.children, level + 1)}
      </li>`;
    });

    html += "</ul>";
    return html;
  }

  return generateTocHTML(tocTree);
}

// 生成目录HTML
const tableOfContents = generateTableOfContents(headings);
---

<Layout
  title={article.data.title}
  description={description}
  date={article.data.date}
  tags={article.data.tags}
  pageType="article"
>
  <div class="max-w-5xl py-8">
    <!-- 阅读进度条 -->
    <div
      class="fixed top-0 left-0 w-full h-1 bg-transparent z-50"
      id="progress-container"
    >
      <div
        class="h-full w-0 bg-primary-500 transition-width duration-100"
        id="progress-bar"
      >
      </div>
    </div>

    <!-- 文章头部 - 包含面包屑，保持不变 -->
    <header class="mb-8">
      <!-- 导航区域/面包屑 - 不参与视图切换 -->
      <div
        class="bg-white dark:bg-gray-800 rounded-xl p-4 mb-6 shadow-lg border border-gray-200 dark:border-gray-700 relative z-10"
      >
        <div
          class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"
        >
          <div class="w-full overflow-hidden">
            <Breadcrumb
              pageType="article"
              pathSegments={pathSegments}
              searchParams={searchParams}
              articleTitle={article.data.title}
              path={section}
            />
          </div>
        </div>
      </div>

      <!-- 文章过期提醒 - 放入article-content容器内 -->
    </header>

    <!-- 文章内容区域 - 只有这部分参与视图切换 -->
    <div id="article-content">
      <!-- 文章过期提醒 -->
      {
        (() => {
          const publishDate = article.data.date;
          const currentDate = new Date();
          const daysDiff = Math.floor(
            (currentDate.getTime() - publishDate.getTime()) /
              (1000 * 60 * 60 * 24),
          );

          if (
            ARTICLE_EXPIRY_CONFIG.enabled &&
            daysDiff > ARTICLE_EXPIRY_CONFIG.expiryDays
          ) {
            return (
              <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-4">
                <div class="flex">
                  <div class="flex-shrink-0">
                    <svg
                      class="h-5 w-5 text-yellow-400"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        fill-rule="evenodd"
                        d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
                        clip-rule="evenodd"
                      />
                    </svg>
                  </div>
                  <div class="ml-3">
                    <p class="text-sm text-yellow-700">
                      {ARTICLE_EXPIRY_CONFIG.warningMessage}
                    </p>
                  </div>
                </div>
              </div>
            );
          }
          return null;
        })()
      }

      <h1 class="text-3xl font-bold mb-4 text-gray-900 dark:text-gray-100">
        {article.data.title}
      </h1>

      <div
        class="flex flex-wrap items-center gap-4 text-sm text-secondary-600 dark:text-secondary-400 mb-4"
      >
        <time
          datetime={article.data.date.toISOString()}
          class="flex items-center"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            class="h-4 w-4 mr-1"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
            ></path>
          </svg>
          {article.data.date.toLocaleDateString("zh-CN")}
        </time>
      </div>

      {
        article.data.tags && article.data.tags.length > 0 && (
          <div class="flex flex-wrap gap-2 mb-6">
            {article.data.tags.map((tag: string) => (
              <a
                href={`/filtered?tags=${tag}`}
                class="text-xs bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 py-1 px-2 rounded hover:bg-primary-100 dark:hover:bg-primary-800/30"
                data-astro-prefetch="hover"
              >
                #{tag}
              </a>
            ))}
          </div>
        )
      }

      <article
        class="prose prose-lg dark:prose-invert prose-primary prose-table:rounded-lg prose-table:border-separate prose-table:border-2 prose-thead:bg-primary-50 dark:prose-thead:bg-gray-800 prose-ul:list-disc prose-ol:list-decimal prose-li:my-1 prose-blockquote:border-l-4 prose-blockquote:border-primary-500 prose-blockquote:bg-gray-100 prose-blockquote:dark:bg-gray-800 prose-a:text-primary-600 prose-a:dark:text-primary-400 prose-a:no-underline prose-a:border-b prose-a:border-primary-300 prose-a:hover:border-primary-600 max-w-none mb-12"
      >
        <Content />
      </article>

      <!-- 相关文章 -->
      {
        relatedArticles.length > 0 && (
          <aside class="mt-12 pt-8 border-t border-secondary-200 dark:border-gray-700">
            <h2 class="text-2xl font-bold mb-6 text-primary-900 dark:text-primary-100">
              {relatedArticlesMatchType === "tag"
                ? "相关文章"
                : relatedArticlesMatchType === "directory"
                  ? "同类文章"
                  : "推荐阅读"}
            </h2>
            <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
              {relatedArticles.map((relatedArticle: ArticleEntry) => (
                <a
                  href={getArticleUrl(relatedArticle.id)}
                  class="article-card"
                  data-astro-prefetch="viewport"
                >
                  <div class="article-card-content">
                    <div class="article-card-icon">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        class="h-5 w-5"
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
                        />
                      </svg>
                    </div>
                    <div class="article-card-body">
                      <h3 class="article-card-title">
                        {relatedArticle.data.title}
                      </h3>
                      <p class="article-card-summary">
                        {generateArticleSummary(relatedArticle)}
                      </p>
                      <div class="article-card-footer">
                        <time
                          datetime={relatedArticle.data.date.toISOString()}
                          class="article-card-date"
                        >
                          {relatedArticle.data.date.toLocaleDateString(
                            "zh-CN",
                            {
                              year: "numeric",
                              month: "long",
                              day: "numeric",
                            },
                          )}
                        </time>
                        <span class="article-card-read-more">阅读全文</span>
                      </div>
                    </div>
                  </div>
                </a>
              ))}
            </div>
          </aside>
        )
      }

      <!-- 返回顶部按钮 -->
      <button
        id="back-to-top"
        class="fixed bottom-8 right-8 w-12 h-12 rounded-full bg-primary-500 dark:bg-primary-600 text-white shadow-md flex items-center justify-center opacity-0 invisible translate-y-5 hover:bg-primary-600 dark:hover:bg-primary-700"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          class="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M5 10l7-7m0 0l7 7m-7-7v18"
          ></path>
        </svg>
      </button>
    </div>

    <!-- 目录 -->
    <section
      class="hidden 2xl:block fixed right-[calc(50%-44rem)] top-20 w-64 z-30 transition-transform duration-300"
      id="toc-panel"
    >
      <div
        class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl flex flex-col backdrop-blur-sm bg-opacity-95 dark:bg-opacity-95 shadow-lg transition-opacity duration-300"
      >
        <div
          class="border-b border-gray-200 dark:border-gray-700 p-4 pb-3 sticky top-0 z-10 rounded-t-xl bg-white dark:bg-gray-800 bg-opacity-95 backdrop-blur-sm"
        >
          <h3
            class="font-bold text-primary-700 dark:text-primary-400 flex items-center gap-2"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              class="h-4 w-4"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M4 6h16M4 12h16M4 18h7"
              ></path>
            </svg>
            文章目录
          </h3>
        </div>
        <div
          id="toc-content"
          class="text-sm p-4 pt-2 overflow-y-auto max-h-[calc(100vh-8rem-42px)] bg-white dark:bg-gray-800 scroll-smooth scrollbar-thin scrollbar-thumb-primary-200 dark:scrollbar-thumb-primary-800 scrollbar-track-transparent"
          set:html={tableOfContents}
        />
      </div>
    </section>
  </div>
  <!-- 文章页面脚本 -->
  <script is:inline>
    // 文章页面交互脚本 - 自销毁模式
    (function () {
      // 集中管理所有事件监听器
      const allListeners = [];

      // 为特殊清理任务准备的数组
      const customCleanupTasks = [];

      // 单独保存清理事件的监听器引用
      const cleanupListeners = [];

      // 添加事件监听器并记录，方便后续统一清理
      function addListener(element, eventType, handler, options) {
        if (!element) {
          return null;
        }

        element.addEventListener(eventType, handler, options);
        allListeners.push({ element, eventType, handler, options });
        return handler;
      }

      // 统一的清理函数，执行完整清理并自销毁
      function selfDestruct() {
        // 1. 先移除普通事件监听器
        allListeners.forEach(({ element, eventType, handler, options }) => {
          try {
            element.removeEventListener(eventType, handler, options);
          } catch (err) {
            console.error("移除事件监听器出错:", err);
          }
        });

        // 清空监听器数组
        allListeners.length = 0;

        // 2. 执行特殊清理任务
        customCleanupTasks.forEach((task) => {
          try {
            task();
          } catch (err) {
            console.error("执行特殊清理任务出错:", err);
          }
        });

        // 清空特殊任务数组
        customCleanupTasks.length = 0;

        // 3. 最后移除清理事件监听器自身
        cleanupListeners.forEach(({ element, eventType, handler, options }) => {
          try {
            element.removeEventListener(eventType, handler, options);
          } catch (err) {
            console.error("移除清理监听器出错:", err);
          }
        });
      }

      // 注册清理事件，并保存引用
      function registerCleanupEvents() {
        // 创建统一的清理处理函数
        const cleanup = () => {
          selfDestruct();
        };

        // 定义需要监听的所有清理事件
        const cleanupEventTypes = [
          {
            element: document,
            eventType: "astro:before-swap",
            options: { once: true },
          },
          {
            element: window,
            eventType: "beforeunload",
            options: { once: true },
          },
          {
            element: document,
            eventType: "page-transition",
            options: { once: true },
          },
        ];

        // 注册所有清理事件
        cleanupEventTypes.forEach(({ element, eventType, options }) => {
          // 添加事件监听
          element.addEventListener(eventType, cleanup, options);

          // 保存事件引用到清理列表
          cleanupListeners.push({
            element,
            eventType,
            handler: cleanup,
            options,
          });
        });
      }

      // 初始化所有功能
      function initializeFeatures() {
        // 1. 代码块复制功能
        function setupCodeCopy() {
          const copyButtons = document.querySelectorAll(".code-block-copy");
          if (copyButtons.length === 0) {
            return;
          }

          copyButtons.forEach((button) => {
            addListener(button, "click", async () => {
              try {
                const encodedCode = button.getAttribute("data-code");
                if (!encodedCode) return;

                // 解码Base64编码的代码，正确处理UTF-8字符
                const code = new TextDecoder("utf-8").decode(
                  Uint8Array.from(atob(encodedCode), (c) => c.charCodeAt(0)),
                );
                await navigator.clipboard.writeText(code);

                // 保存原始SVG
                const originalSVG = button.innerHTML;

                // 添加已复制状态类，伪元素会自动显示"已复制"文本
                button.classList.add("copied");

                // 更改SVG为对勾图标
                button.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                  <path d="M20 6L9 17l-5-5"></path>
                </svg>
              `;

                setTimeout(() => {
                  // 恢复原始状态
                  button.classList.remove("copied");
                  button.innerHTML = originalSVG;
                }, 2000);
              } catch (err) {
                console.error("复制失败:", err);
                // 更改SVG为错误图标，伪元素文本不变
                button.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                  <circle cx="12" cy="12" r="10"></circle>
                  <line x1="12" y1="8" x2="12" y2="12"></line>
                  <line x1="12" y1="16" x2="12.01" y2="16"></line>
                </svg>
              `;
                // 添加特殊类以显示"失败"文本
                button.classList.add("copy-failed");

                setTimeout(() => {
                  // 恢复原始状态
                  button.classList.remove("copy-failed");
                  button.innerHTML = `
                  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                    <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                    <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                  </svg>
                `;
                }, 2000);
              }
            });
          });
        }

        // 2. 阅读进度条
        function setupProgressBar() {
          const progressBar = document.getElementById("progress-bar");
          const backToTopButton = document.getElementById("back-to-top");

          if (!progressBar) {
            return;
          }

          function updateReadingProgress() {
            const scrollTop =
              window.scrollY || document.documentElement.scrollTop;
            const scrollHeight =
              document.documentElement.scrollHeight -
              document.documentElement.clientHeight;
            const progress = (scrollTop / scrollHeight) * 100;

            progressBar.style.width = `${progress}%`;

            if (backToTopButton) {
              if (scrollTop > 300) {
                backToTopButton.classList.add(
                  "opacity-100",
                  "visible",
                  "translate-y-0",
                );
                backToTopButton.classList.remove(
                  "opacity-0",
                  "invisible",
                  "translate-y-5",
                );
              } else {
                backToTopButton.classList.add(
                  "opacity-0",
                  "invisible",
                  "translate-y-5",
                );
                backToTopButton.classList.remove(
                  "opacity-100",
                  "visible",
                  "translate-y-0",
                );
              }
            }
          }

          addListener(window, "scroll", updateReadingProgress);

          if (backToTopButton) {
            addListener(backToTopButton, "click", () => {
              window.scrollTo({
                top: 0,
                behavior: "smooth",
              });
            });
          }

          // 初始更新一次进度条
          updateReadingProgress();
        }

        // 3. 目录交互
        function setupTableOfContents() {
          const tocContent = document.getElementById("toc-content");
          const tocPanel = document.querySelector("#toc-panel");

          if (!tocPanel || !tocContent) {
            return;
          }

          // 检查窗口大小调整目录面板显示
          function checkTocVisibility() {
            if (window.innerWidth < 1536) {
              tocPanel.classList.add("hidden");
            } else {
              tocPanel.classList.remove("hidden");
            }
          }

          addListener(window, "resize", checkTocVisibility);
          checkTocVisibility();

          // 处理目录折叠/展开功能
          const tocToggles = tocContent.querySelectorAll(".toc-toggle");

          tocToggles.forEach((toggle) => {
            addListener(toggle, "click", (e) => {
              e.preventDefault();
              e.stopPropagation();

              const expanded = toggle.getAttribute("aria-expanded") === "true";
              toggle.setAttribute("aria-expanded", expanded ? "false" : "true");

              // 切换子菜单显示状态
              const listItem = toggle.closest(".toc-item");
              if (listItem) {
                const sublist = listItem.querySelector(".toc-sublist");
                if (sublist) {
                  if (expanded) {
                    // 收起子菜单
                    sublist.classList.add("hidden");
                    sublist.setAttribute("aria-expanded", "false");
                    toggle.querySelector("svg").classList.remove("rotate-180");
                  } else {
                    // 展开子菜单
                    sublist.classList.remove("hidden");
                    sublist.setAttribute("aria-expanded", "true");
                    toggle.querySelector("svg").classList.add("rotate-180");
                  }
                }
              }
            });
          });

          // 处理目录链接点击跳转
          const tocLinks = tocContent.querySelectorAll(".toc-link");

          tocLinks.forEach((link) => {
            addListener(link, "click", (e) => {
              e.preventDefault();
              const targetId = link.getAttribute("href")?.substring(1);
              if (!targetId) return;

              const targetElement = document.getElementById(targetId);
              if (targetElement) {
                const offset = 100;
                const targetPosition =
                  targetElement.getBoundingClientRect().top +
                  window.scrollY -
                  offset;

                window.scrollTo({
                  top: targetPosition,
                  behavior: "smooth",
                });

                // 增强高亮效果
                targetElement.classList.add(
                  "bg-primary-50",
                  "dark:bg-primary-900/20",
                );
                setTimeout(() => {
                  targetElement.classList.remove(
                    "bg-primary-50",
                    "dark:bg-primary-900/20",
                  );
                }, 2000);
              }
            });
          });

          // 监听滚动以更新当前活动的目录项
          const article = document.querySelector("article");
          if (!article) {
            return;
          }

          let ticking = false;

          function updateActiveHeading() {
            const headings = Array.from(
              article.querySelectorAll("h1, h2, h3, h4, h5, h6"),
            );
            const tocLinks = Array.from(
              tocContent.querySelectorAll(".toc-link"),
            );

            // 清除所有活动状态
            tocLinks.forEach((link) => {
              // 移除活动类
              link.classList.remove(
                "toc-link-active",
                "text-primary-600",
                "dark:text-primary-400",
                "font-medium",
              );
            });

            // 找出当前可见的标题
            const scrollPosition = window.scrollY + 150;
            let currentHeading = null;

            for (const heading of headings) {
              const headingTop =
                heading.getBoundingClientRect().top + window.scrollY;
              if (headingTop <= scrollPosition) {
                currentHeading = heading;
              } else {
                break;
              }
            }

            // 记录当前活动的项目和其所有父级
            const activeItems = new Set();

            // 高亮当前标题对应的目录项并展开父菜单
            if (currentHeading) {
              const id = currentHeading.getAttribute("id");
              if (id) {
                const activeLink = tocLinks.find(
                  (link) => link.getAttribute("href") === `#${id}`,
                );
                if (activeLink) {
                  // 高亮当前目录项
                  activeLink.classList.add(
                    "toc-link-active",
                    "text-primary-600",
                    "dark:text-primary-400",
                    "font-medium",
                  );

                  // 展开当前激活项的所有父菜单并收集到活动项集合中
                  let parent = activeLink.closest(".toc-item");
                  while (parent) {
                    // 添加到活动项目集合
                    activeItems.add(parent);

                    const parentSublist = parent.querySelector(".toc-sublist");
                    const parentToggle = parent.querySelector(".toc-toggle");

                    if (
                      parentSublist &&
                      parentSublist.classList.contains("hidden")
                    ) {
                      // 使用平滑动画展开
                      parentSublist.classList.remove("hidden");
                      parentSublist.setAttribute("aria-expanded", "true");

                      if (parentToggle) {
                        parentToggle.setAttribute("aria-expanded", "true");
                        parentToggle
                          .querySelector("svg")
                          ?.classList.add("rotate-180");
                      }
                    }

                    // 向上查找父级
                    parent = parent.parentElement?.closest(".toc-item");
                  }

                  // 确保当前激活的目录项在可视区域内 - 添加平滑滚动
                  setTimeout(() => {
                    // 延迟执行确保DOM已更新
                    if (tocContent) {
                      // 重新计算activeLink的位置，因为父菜单可能已展开
                      const linkRect = activeLink.getBoundingClientRect();
                      const containerRect = tocContent.getBoundingClientRect();

                      // 检查当前项是否在目录容器的可视区域内
                      const isInView =
                        linkRect.top >= containerRect.top &&
                        linkRect.bottom <= containerRect.bottom;

                      // 如果当前激活项不在视口内，滚动目录
                      if (!isInView) {
                        // 计算滚动位置，使激活项在容器中居中
                        const scrollTop =
                          tocContent.scrollTop +
                          (linkRect.top - containerRect.top) -
                          containerRect.height / 2 +
                          linkRect.height / 2;

                        tocContent.scrollTo({
                          top: scrollTop,
                          behavior: "smooth",
                        });
                      }
                    }
                  }, 100); // 添加短延迟确保DOM已更新
                }
              }
            }

            // 关闭不在当前活动路径上的所有子菜单 - 使用平滑动画
            const allItems = Array.from(
              tocContent.querySelectorAll(".toc-item"),
            );
            allItems.forEach((item) => {
              // 如果不在活动路径上且有子菜单
              if (!activeItems.has(item)) {
                const sublist = item.querySelector(".toc-sublist");
                const toggle = item.querySelector(".toc-toggle");

                if (sublist && !sublist.classList.contains("hidden")) {
                  sublist.classList.add("hidden");
                  sublist.setAttribute("aria-expanded", "false");

                  if (toggle) {
                    toggle.setAttribute("aria-expanded", "false");
                    toggle.querySelector("svg")?.classList.remove("rotate-180");
                  }
                }
              }
            });
          }

          addListener(window, "scroll", () => {
            if (!ticking) {
              window.requestAnimationFrame(() => {
                updateActiveHeading();
                ticking = false;
              });
              ticking = true;
            }
          });

          // 初始化时收起所有子菜单
          const topLevelToggles = tocContent.querySelectorAll(
            ".toc-list > .toc-item > .toc-item-container > .toc-toggle",
          );
          topLevelToggles.forEach((toggle) => {
            toggle.setAttribute("aria-expanded", "false");
            const sublist = toggle
              .closest(".toc-item")
              .querySelector(".toc-sublist");
            if (sublist) {
              sublist.classList.add("hidden");
              sublist.setAttribute("aria-expanded", "false");
            }
          });

          // 初始更新一次活动标题，确保相关父菜单展开
          updateActiveHeading();
        }

        // 4. Mermaid图表渲染
        function setupMermaid() {
          // 查找所有mermaid代码块
          const mermaidBlocks = document.querySelectorAll(
            "pre.language-mermaid, pre > code.language-mermaid, .mermaid",
          );

          if (mermaidBlocks.length === 0) {
            return;
          }

          // 动态加载mermaid库
          const script = document.createElement("script");
          script.src =
            "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js";

          script.onload = function () {
            if (!window.mermaid) {
              console.error("Mermaid库加载后window.mermaid不存在");
              return;
            }

            // 初始化mermaid配置
            window.mermaid.initialize({
              startOnLoad: false,
              theme: "default",
              securityLevel: "loose",
            });

            // 将所有mermaid代码块转换为可渲染的格式
            mermaidBlocks.forEach((block, index) => {
              // 获取mermaid代码
              let code = "";

              // 检查元素类型并相应处理
              if (
                block.tagName === "CODE" &&
                block.classList.contains("language-mermaid")
              ) {
                // 处理 code.language-mermaid 元素
                code = block.textContent || "";
                const pre = block.closest("pre");
                if (pre) {
                  // 创建新的div元素替换整个pre
                  const div = document.createElement("div");
                  div.className = "mermaid";
                  div.id = "mermaid-diagram-" + index;
                  div.textContent = code;
                  pre.parentNode.replaceChild(div, pre);
                }
              } else if (
                block.tagName === "PRE" &&
                block.classList.contains("language-mermaid")
              ) {
                // 处理 pre.language-mermaid 元素
                code = block.textContent || "";
                const div = document.createElement("div");
                div.className = "mermaid";
                div.id = "mermaid-diagram-" + index;
                div.textContent = code;
                block.parentNode.replaceChild(div, block);
              } else if (
                block.classList.contains("mermaid") &&
                block.tagName !== "DIV"
              ) {
                // 如果是其他带mermaid类的元素但不是div，转换为div
                code = block.textContent || "";
                const div = document.createElement("div");
                div.className = "mermaid";
                div.id = "mermaid-diagram-" + index;
                div.textContent = code;
                block.parentNode.replaceChild(div, block);
              }
            });

            // 初始化渲染
            try {
              window.mermaid.run().catch((err) => {
                console.error("Mermaid渲染出错:", err);
              });
            } catch (error) {
              console.error("初始化Mermaid渲染失败:", error);
            }
          };

          script.onerror = function () {
            console.error("加载Mermaid库失败");
            // 显示错误信息
            mermaidBlocks.forEach((block) => {
              if (block.tagName === "CODE") block = block.closest("pre");
              if (block) {
                block.innerHTML =
                  '<div class="mermaid-error-message">无法加载Mermaid图表库</div>';
              }
            });
          };

          document.head.appendChild(script);

          // 添加Mermaid清理任务
          customCleanupTasks.push(() => {
            // 移除脚本标签
            if (script.parentNode) {
              script.parentNode.removeChild(script);
            }

            // 清除全局mermaid对象
            if (window.mermaid) {
              try {
                // 尝试清理mermaid内部状态
                if (typeof window.mermaid.destroy === "function") {
                  window.mermaid.destroy();
                }
                window.mermaid = undefined;
              } catch (e) {
                console.error("清理mermaid对象出错:", e);
              }
            }

            // 移除页面上可能留下的mermaid相关元素
            try {
              // 移除所有可能的mermaid样式和元素
              const mermaidElements = [
                "#mermaid-style",
                "#mermaid-cloned-styles",
                ".mermaid-svg-reference",
                'style[id^="mermaid-"]',
              ];

              document
                .querySelectorAll(mermaidElements.join(", "))
                .forEach((el) => {
                  if (el && el.parentNode) {
                    el.parentNode.removeChild(el);
                  }
                });
            } catch (e) {
              console.error("清理Mermaid元素时出错:", e);
            }
          });
        }

        // 启动所有功能
        setupCodeCopy();
        setupProgressBar();
        setupTableOfContents();
        setupMermaid();
      }

      // 执行初始化
      registerCleanupEvents();
      initializeFeatures();
    })();
  </script>
</Layout>
